/*
** Copyright (C) 2009 Joshua Brent Marsh <joshua@icub3d.com>
**  
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 3 of the License, or
** (at your option) any later version.
**  
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**  
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**  
*/

/* $Id: test_buffer.c 32 2009-10-28 22:51:19Z joshua@icub3d.com $ */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

#include <CUnit/Basic.h>

#include "../src/buffer.h"

#include "test_buffer.h"

Buffer *b;

int
init_test_buffer_suite ()
{
  b = buffer_create (32);
  if (b == NULL)
    return 1;
  else
    return 0;
}

int
clean_test_buffer_suite ()
{
  buffer_destroy (b, 1);

  return 0;
}


void
test_buffer_read_write ()
{
  char *d = "This is a test.";
  char *t = "Tis not a test.";
  char z[32];
  size_t read;
  char *x;

  read = buffer_get (b, d, strlen (d) + 1);
  CU_ASSERT (read == 16);

  CU_ASSERT (buffer_get_position (b) == 16);
  
  buffer_mark (b);

  x = buffer_array (b);
  CU_ASSERT (x == b->data);
  CU_ASSERT (strcmp (x, "This is a test.") == 0);

  read = buffer_get (b, t, strlen (t) + 1);
  CU_ASSERT (read == 16);

  CU_ASSERT (buffer_get_position (b) == 32);

  x = buffer_array (b);
  CU_ASSERT (x == b->data);
  CU_ASSERT (memcmp (x, "This is a test.\0Tis not a test.\0", 32) == 0);

  read = buffer_get (b, t, strlen (t) + 1);
  CU_ASSERT (read == 0);

  buffer_flip (b);
  CU_ASSERT (buffer_get_position (b) == 0);

  read = buffer_put (b, z, 32);
  CU_ASSERT (read == 32);
  CU_ASSERT (memcmp (z, "This is a test.\0Tis not a test.\0", 32) == 0);

  buffer_reset (b);
  CU_ASSERT (buffer_get_position (b) == 32);

  buffer_set_position (b, 16);
  CU_ASSERT (buffer_get_position (b) == 16);
  buffer_mark (b);

  buffer_set_position (b, 32);
  CU_ASSERT (buffer_get_position (b) == 32);

  buffer_reset (b);
  CU_ASSERT (buffer_get_position (b) == 16);

  buffer_flip (b);
  CU_ASSERT (buffer_get_position (b) == 0);

  read = buffer_put (b, z, 32);
  CU_ASSERT (read == 16);
  CU_ASSERT (strcmp (z, "This is a test.") == 0);
  
  buffer_rewind (b);
  CU_ASSERT (buffer_get_position (b) == 0);
  CU_ASSERT (buffer_remaining (b) == 16);

  buffer_set_limit (b, 32);
  CU_ASSERT (buffer_remaining (b) == 32);

  buffer_set_position (b, 10);
  CU_ASSERT (buffer_remaining (b) == 22);

  buffer_clear (b);

  read = buffer_put (b, z, 4);
  CU_ASSERT (read == 4);
  CU_ASSERT (memcmp (z, "This", 4) == 0);

}

void
test_buffer_abs_read_write ()
{
  char x[32];
  size_t read;

  /* "This is a test.\0Tis not a test.\0" */

  buffer_clear (b);

  read = buffer_put_abs (b, x, 6, 10);
  CU_ASSERT (read == 6);
  CU_ASSERT (strcmp (x, "test.") == 0);

  read = buffer_get_abs (b, "sink.", 6, 10);
  CU_ASSERT (read == 6);

  read = buffer_put_abs (b, x, 6, 10);
  CU_ASSERT (read == 6);
  CU_ASSERT (strcmp (x, "sink.") == 0);
}

void
test_buffer_slice_wrap_dup ()
{
  /* "This is a sink.\0Tis not a test.\0" */

  Buffer *s, *t;
  char *sdata = "Hello World!";
  char x[13];

  buffer_set_position (b, 10);
  buffer_set_limit (b, 20);

  s = buffer_slice (b);
  CU_ASSERT (s != NULL);
  CU_ASSERT (buffer_remaining (s) == 10);
  
  buffer_put (s, x, 10);
  CU_ASSERT (memcmp (x, "sink.\0Tis not a", 10) == 0);

  CU_ASSERT (buffer_remaining (s) == 0);
  
  buffer_flip (s);
  buffer_get (s, "kick", 4);
  buffer_put (b, x, 6);
  CU_ASSERT (strcmp (x, "kick.") == 0);

  buffer_destroy (s, 0);

  s = buffer_wrap (sdata, strlen (sdata) + 1);

  CU_ASSERT (buffer_array (s) == sdata);
  
  buffer_put (s, x, 32);

  CU_ASSERT (strcmp (x, sdata) == 0);

  t = buffer_dup (s);
  CU_ASSERT (buffer_get_position (s) == buffer_get_position (t));
  CU_ASSERT (buffer_get_limit (s) == buffer_get_limit (t));
  CU_ASSERT (buffer_size (s) == buffer_size (t));
  CU_ASSERT (buffer_array (s) == buffer_array (t));

  buffer_destroy (s, 0);

  s = buffer_copy (t);

  CU_ASSERT (buffer_array (s) != buffer_array (t));
  CU_ASSERT (buffer_size (s) == buffer_size (t));
  CU_ASSERT (memcmp (buffer_array (s), buffer_array (t), buffer_size (s)) == 0);

  buffer_destroy (s, 1);
  buffer_destroy (t, 0);
  
}


void
test_buffer_fread ()
{
  /* Not Written. */
}

void
test_buffer_fwrite ()
{
  /* Not Written. */
}


int
make_buffer_suite (CU_pSuite s)
{
  s = CU_add_suite ("Test Buffer Suite", 
		    init_test_buffer_suite, 
		    clean_test_buffer_suite);
  if (s == NULL)
    {
      return CU_get_error();
    }

  if (CU_add_test (s, "test buffer_read_write", 
		   test_buffer_read_write) == NULL ||
      CU_add_test (s, "test buffer_abs_read_write", 
		   test_buffer_abs_read_write) == NULL ||
      CU_add_test (s, "test buffer_slice_wrap_dup", 
		   test_buffer_slice_wrap_dup) == NULL ||
      CU_add_test (s, "test buffer_fread",  test_buffer_fread) == NULL ||
      CU_add_test (s, "test buffer_fwrite", test_buffer_fwrite) == NULL)
    {
      return CU_get_error();
    }

  return CU_get_error();
}

